package uhf

import "encoding/binary"

type MemBank int

const (
	BankRfu  MemBank = 0
	BankEpc  MemBank = 1
	BankTid  MemBank = 2
	BankUser MemBank = 3
)

type SelectMode byte

const (
	SelectAllOperate       SelectMode = 0x00
	SelectNone             SelectMode = 0x01
	SelectExcludeInventory SelectMode = 0x02
)

type MemoryOperation struct {
	Bank     MemBank
	Mask     []byte
	Password []byte
}

type Sdk interface {
	SetPower(power int) (success bool, err error)
	Write(operation MemoryOperation, startPtr int, payload []byte) (code byte, err error)
	Read(operation MemoryOperation, startPtr int, payload []byte) (code byte, err error)
	Select(params SelectParam) (code byte, err error)
	SetSelectMode(mode SelectMode) (success bool, err error)
	Lock(bank MemBank, lockType LockType, password []byte) (code byte, err error)
	InventoryOnce(onTag func(pc, epc []byte, rssi byte)) (code byte, err error)
}

type Session int

const (
	SessionS0 = 0
	SessionS1 = 1
	SessionS2 = 2
	SessionS3 = 3
	SessionSL = 4
)

type SelParam struct {
	Target  Session
	Action  int
	MemBank MemBank
}

type SelectParam struct {
	SelParam
	StartPtr int // word ptr
	Mask     []byte
}

func (sp *SelectParam) Marshal() (bs []byte) {
	var b = byte(sp.SelParam.Target << 5)
	b |= byte(sp.SelParam.Action << 2)
	b |= byte(sp.SelParam.MemBank)
	bs = append(bs, b)
	ptr := sp.StartPtr * 2 * 8
	ptrBs := make([]byte, 4)
	binary.BigEndian.PutUint32(ptrBs, uint32(ptr))
	bs = append(bs, ptrBs...)
	maskLen := byte(len(sp.Mask) * 8)
	bs = append(bs, maskLen)
	bs = append(bs, 0x00) // disable truncate
	bs = append(bs, sp.Mask...)
	return
}

type LockMask struct {
	KillMask   LockType
	AccessMask LockType
	EpcMash    LockType
	TidMask    LockType
	UserMask   LockType
}

type LockType int

const (
	Open        LockType = 0x00
	OpenForever LockType = 0x01
	Lock        LockType = 0x02
	LockForever LockType = 0x03
)

type LockAction struct {
	KillAction   LockType
	AccessAction LockType
	EpcAction    LockType
	TidAction    LockType
	UserAction   LockType
}

type LockParam struct {
	LockMask
	LockAction
	Password []byte
}

func (p *LockParam) Marshal() (bs []byte) {
	return
}
